// 错误描述
// Created by kenny on 25-11-4.
//
#include <stdio.h>
#include <stdlib.h>
#include "mcp_exception.h"

// 哈希表大小
#define EXCEPTION_TABLE_SIZE 128

// 命令数据
const ExceptionInfo exception_infos[] = {
    // Command Exception
    {INVALID_ACTION, "Invalid action"},
    {EMPTY_STRING, "Empty string"},

    // JSON Exception
    {INVALID_JSON, "Invalid json string"},
    {JSON_NOT_ACTION,  "No 'action' key"},
    {JSON_NOT_COMMAND,  "No 'command' key"},
    {JSON_NOT_SEQUENCE,  "No 'sequence' key"},
    {JSON_INVALID_ACTION, "Invalid action"},
    {JSON_INVALID_COMMAND, "Invalid command"},
};
const int EXCEPTION_COUNT = sizeof(exception_infos) / sizeof(exception_infos[0]);

typedef struct EHashNode {
    int key;               // id
    ExceptionInfo value;   // 信息
    struct EHashNode* next; // 解决哈希冲突
} EHashNode;

typedef struct {
    EHashNode* buckets[EXCEPTION_TABLE_SIZE];
} EHashTable;

EHashTable* exception_table = NULL;

// 哈希函数
unsigned int exception_hash(int key) {
    return key % EXCEPTION_TABLE_SIZE;
}

// 从哈希表查找数据
const ExceptionInfo* emap_get(int key) {
    if (exception_table == NULL) {
        return NULL;
    }

    unsigned int index = exception_hash(key);
    EHashNode* current = exception_table->buckets[index];

    while (current != NULL) {
        if (current->key == key) {
            return &(current->value);
        }
        current = current->next;
    }
    return NULL;
}

// 插入数据到哈希表
void emap_put(int key, const ExceptionInfo* value) {
    if (exception_table == NULL) {
        return;
    }

    unsigned int index = exception_hash(key);
    EHashNode* node = (EHashNode*)malloc(sizeof(EHashNode));

    node->key = key;
    node->value = *value;
    node->next = exception_table->buckets[index];
    exception_table->buckets[index] = node;
}

/**
 * 初始化
 */
void emap_init() {
    // 如果已经初始化，先释放
    if (exception_table != NULL) {
        emap_free();
    }

    // 分配哈希表内存
    exception_table = (EHashTable*)malloc(sizeof(EHashTable));
    if (exception_table == NULL) {
        return;
    }

    // 初始化
    for (int i = 0; i < EXCEPTION_TABLE_SIZE; i++) {
        exception_table->buckets[i] = NULL;
    }
    // 数组压入 map
    for (int i = 0; i < EXCEPTION_COUNT; i++) {
        emap_put(exception_infos[i].code, &exception_infos[i]);
    }
}


// 释放哈希表内存
void emap_free() {
    if (exception_table == NULL) {
        return;
    }

    for (int i = 0; i < EXCEPTION_TABLE_SIZE; i++) {
        EHashNode* current = exception_table->buckets[i];
        while (current != NULL) {
            EHashNode* temp = current;
            current = current->next;
            free(temp);
        }
        exception_table->buckets[i] = NULL;
    }

    // 重要：释放哈希表本身并将指针设为NULL
    free(exception_table);
    exception_table = NULL;
}
